/*
 * Copyright (c) 2017,安徽皖通科技股份有限公司 All rights reserved.
 */

package com.wttech.dzzf.process.service.errordata;

import com.wtkj.vo.dzzf.base.kfwd.FundAccount;
import com.wttech.dzzf.process.dao.ErrorCertDataDao;
import com.wttech.dzzf.process.service.user.UserDetailInfosCreatorService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

/**
 * 错误证件号处理服务实现
 * Created by MaShibo on 2017/10/25.
 */
@Service
public class ErrorCertProcessService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ErrorCertProcessService.class);

    private static final String IDCARD_STR = "身份证";
    private static final int IDCARD_VAL = 0;

    private static final String ORGCERT_STR = "组织机构代码证";
    private static final int ORGCERT_VAL = 101;

    private static final String USER_STR = "个人用户";
    private static final int USERTYPE_VAL = 0;

    private static final String COMPANY_STR = "单位用户";
    private static final int COMPANY_VAL = 1;

    @Resource
    private ErrorCertDataDao errorCertDataDao;

    @Resource
    private ThreadPoolTaskExecutor executor;

    @Resource
    private UserDetailInfosCreatorService userDetailInfosCreatorService;

    /**
     * Excel文件路径
     */
    private String excelFilePath;

    public void process() {
        try (OPCPackage pkg = OPCPackage.open(new File(excelFilePath))) {
            XSSFWorkbook wb = new XSSFWorkbook(pkg);
            LOGGER.info("读取文件{}成功", excelFilePath);
            for (Sheet sheet : wb) {
                LOGGER.info("开始解析Sheet[{}]", sheet.getSheetName());
                int rowStart = sheet.getFirstRowNum();
                int rowEnd = sheet.getLastRowNum();
                //从第二行开始遍历数据
                List<Future<Void>> futures = new ArrayList<>(15000);
                for (int rowNum = rowStart + 1; rowNum < rowEnd; rowNum++) {
                    Row row = sheet.getRow(rowNum);
                    if (row == null) {
                        continue;
                    }
                    ErrorCert errorCert = new ErrorCert();
                    errorCert.setUserName(row.getCell(0).getStringCellValue());
                    errorCert.setUserType(row.getCell(1).getStringCellValue());
                    errorCert.setUserIdType(row.getCell(2).getStringCellValue());
                    errorCert.setUserIdNum(row.getCell(3).getStringCellValue());
                    errorCert.setRegisteredDate(row.getCell(4).getStringCellValue());
                    errorCert.setEcardNo(row.getCell(5).getStringCellValue());
                    futures.add(executor.submit(new SubProcessThread(errorCert, rowNum)));
                }
                userDetailInfosCreatorService.getFutureResult(futures);
                executor.shutdown();
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }

    }


    private class SubProcessThread implements Callable<Void> {

        private ErrorCert errorCert;

        private int rowNum;

        public SubProcessThread(ErrorCert errorCert, int rowNum) {
            this.errorCert = errorCert;
            this.rowNum = rowNum;
        }

        @Override
        public Void call() throws Exception {
            LOGGER.info("开始处理第{}行数据", rowNum);
            processErrorCertData(errorCert);
            return null;
        }

        private void processErrorCertData(ErrorCert errorCert) {
            try {
                String cardNo = errorCert.getEcardNo().substring(4);
                FundAccount fundAccount = errorCertDataDao.queryFundAccountByCardNo(cardNo);
                if (fundAccount != null) {
                    determineUserIdType(errorCert.getUserIdType()).ifPresent(fundAccount::setCertifiType);
                    determineUserType(errorCert.getUserType()).ifPresent(fundAccount::setOwnerType);
                    fundAccount.setCompanyLic(errorCert.getUserIdNum());
                    fundAccount.setFundAccountName(errorCert.getUserName());
                    int count = errorCertDataDao.updateFundAccountInfos(fundAccount);
                    if (count < 1) {
                        LOGGER.error("资金账户信息{}更新失败", fundAccount);
                    }
                } else {
                    LOGGER.warn("卡号{}不存在对应的资金账户信息", errorCert.getEcardNo());
                }
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
                LOGGER.info("错误的记录：{}", errorCert);
            }
        }
    }

    private Optional<Integer> determineUserIdType(String userIdType) {
        Integer userIdTypeVal = null;
        if (StringUtils.equals(userIdType, IDCARD_STR)) {
            userIdTypeVal = IDCARD_VAL;
        }
        if (StringUtils.equals(userIdType, ORGCERT_STR)) {
            userIdTypeVal = ORGCERT_VAL;
        }
        return Optional.ofNullable(userIdTypeVal);
    }

    private Optional<Integer> determineUserType(String userType) {
        Integer userTypeVal = null;
        if (StringUtils.equals(userType, USER_STR)) {
            userTypeVal = USERTYPE_VAL;
        }
        if (StringUtils.equals(userType, COMPANY_STR)) {
            userTypeVal = COMPANY_VAL;
        }
        return Optional.ofNullable(userTypeVal);
    }

    public String getExcelFilePath() {
        return excelFilePath;
    }

    public void setExcelFilePath(String excelFilePath) {
        this.excelFilePath = excelFilePath;
    }

    @Data
    @EqualsAndHashCode
    private class ErrorCert {
        private String userName;
        private String userType;
        private String userIdType;
        private String userIdNum;
        private String registeredDate;
        private String ecardNo;
    }

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ErrorCertProcessService errorCertProcessService = context.getBean(ErrorCertProcessService.class);
        errorCertProcessService.setExcelFilePath("C:\\Users\\MaShibo\\Desktop\\中国银行错误证件号(第一轮自测）.xlsx");
        errorCertProcessService.process();
    }
}
